package com.tju.backend.service.business.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tju.backend.dao.sys_role_user.SysRoleUserMapper;
import com.tju.backend.dao.sys_user.SysUserMapper;
import com.tju.backend.entity.SysRoleUser;
import com.tju.backend.entity.SysUser;
import com.tju.backend.service.business.SysUserService;
import com.tju.backend.plugin.common.GlobalCall;
import com.tju.backend.service.common.ServiceException;
import com.tju.backend.utils.bcrypt.BCryptPasswordEncoderUtil;
import com.tju.backend.utils.result.*;
import com.tju.backend.utils.tool.ChineseExceptionUtils;
import com.tju.backend.utils.tool.ClientParameters;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

/**
 * 用户实现类
 *
 * @USER: CLS
 */
@Slf4j
@Service
public class SysUserServiceImpl implements SysUserService {

    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    private SysRoleUserMapper sysRoleUserMapper;
    @Autowired
    private BCryptPasswordEncoderUtil bCryptPasswordEncoderUtil;
    @Autowired
    private ChineseExceptionUtils zh_CN;

    /**
     * 通过账号查询用户
     *
     * @param username
     * @return
     */
    @Override
    public SysUser getUserByUserName(String username) {
        return userMapper.getUserByUserName(username);
    }

    /**
     * 个性化验证登录
     *
     * @param username    账号
     * @param rawPassword 原始密码
     * @return
     */
    @Override
    public boolean checkLogin(String username, String rawPassword) throws Exception {
        SysUser userEntity = getUserByUserName(username);
        Optional.ofNullable(userEntity).orElseThrow(() -> new Exception("账号不存在，请重新尝试！"));
        String encodedPassword = userEntity.getLoginPassword();   //加密的密码
        if (!bCryptPasswordEncoderUtil.matches(rawPassword, encodedPassword)) {//和加密后的密码进行比配
            throw new Exception("密码不正确！"); //设置友好提示
        } else {
            return true;
        }
    }

    /**
     * 查询用户
     *
     * @param parameters
     * @return
     */
    @Override
    public Result<Object> selUser(ClientParameters parameters) {
        try {
            IPage<SysUser> iPage = Optional.ofNullable(parameters)
                    .filter(p -> (p.getPage() != null && p.getLimit() != null))//过滤
                    .map(s -> {
                        Page<SysUser> page = new Page<>(s.getPage(), s.getLimit());
                        return userMapper.selectPageExt(page, parameters);
                    })
                    .orElseThrow(() -> new ServiceException(zh_CN.NoPagination));
            Result<Object> s = ResultUtil.success(ResultEnum.SUCCESS, iPage.getRecords(), iPage.getTotal());
            s.setCode(0);//根据layui数据表格的格式来
            return s;
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * 新增用户
     *
     * @param sysUser
     * @return
     */
    @Override
    @Transactional
    public Result<Object> addUser(SysUser sysUser) {
        try {
            QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
            wrapper.eq("login_name", sysUser.getLoginName());
            SysUser user = userMapper.selectOne(wrapper);
            sysUser.setLoginPassword(BCryptPasswordEncoderUtil.encrypt(sysUser.getLoginPassword()));
            Object count = Optional.ofNullable(user)
                    .map(u -> {
                        throw new ServiceException(zh_CN.USER_OCCUPY);
                    })
                    .orElseGet(() -> {
                        int s = userMapper.insert(sysUser);
                        SysRoleUser roleUser = new SysRoleUser(sysUser.getId(), sysUser.getPower());
                        s += sysRoleUserMapper.insert(roleUser);
                        return s;
                    });
            Optional.ofNullable(count)
                    .filter(c -> String.valueOf(c).equals("2"))
                    .map(c -> "")
                    .orElseThrow(() -> new ServiceException(zh_CN.ADD_FAILED));
            return ResultUtil.success(ResultEnum.SUCCESS);
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
    }


    /**
     * 修改用户信息
     *
     * @param sysUser
     * @return
     */
    @Override
    @Transactional
    public Object updateUser(SysUser sysUser) {
        try {
            Object count = Optional.ofNullable(sysUser.getPower())
                    .map(u -> userMapper.selectById(sysUser.getId())) //根据前端传过来的id查询用户信息
                    .map(u -> {
                        QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
                        wrapper.eq("login_name", sysUser.getLoginName());
                        //根据登录名查询用户数据
                        SysUser user1 = userMapper.selectOne(wrapper);
                        return Optional.ofNullable(user1)
                                .map(user -> {
                                    //登录名是否用过
                                    if (!u.getLoginName().equals(user.getLoginName())) {
                                        throw new ServiceException(zh_CN.CfUserId);
                                    }
                                    //密码相同不处理
                                    if (!sysUser.getLoginPassword().equals(user.getLoginPassword())) {
                                        sysUser.setLoginPassword(BCryptPasswordEncoderUtil.encrypt(sysUser.getLoginPassword()));
                                    }
                                    return userMapper.update(sysUser, wrapper);
                                })
                                .orElseGet(() -> {
                                    sysUser.setLoginPassword(BCryptPasswordEncoderUtil.encrypt(sysUser.getLoginPassword()));
                                    wrapper.clear();
                                    wrapper.eq("id", sysUser.getId());
                                    return userMapper.update(sysUser, wrapper);
                                });
                    })
                    .map(u -> {
                        QueryWrapper<SysRoleUser> sruWrapper = new QueryWrapper<>();
                        sruWrapper.eq("sys_user_id", sysUser.getId());
                        SysRoleUser roleUser = new SysRoleUser();
                        roleUser.setSysRoleId(sysUser.getPower());
                        return sysRoleUserMapper.update(roleUser, sruWrapper);
                    })
                    .orElseThrow(() -> new ServiceException(zh_CN.IdAnomaly));
            Optional.ofNullable(count)
                    .filter(c -> String.valueOf(c).equals("1"))
                    .map(c -> "")
                    .orElseThrow(() -> new ServiceException(zh_CN.ADD_FAILED));
            return ResultUtil.success(ResultEnum.SUCCESS);
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
    }

    /**
     * 删除用户信息
     *
     * @param sysUser
     * @return
     */
    @Override
    public Result<Object> delUser(SysUser sysUser) {
        try {
            Optional.ofNullable(sysUser.getId())
                    .map(u -> {
                        QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
                        wrapper.eq("id", sysUser.getId());
                        return userMapper.selectOne(wrapper);
                    })
                    .map(u -> {
                        userMapper.deleteById(u.getId());
                        QueryWrapper<SysRoleUser> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("sys_user_id", u.getId());
                        SysRoleUser sysRoleUser = sysRoleUserMapper.selectOne(queryWrapper);
                        sysRoleUserMapper.deleteById(sysRoleUser.getId());
                        GlobalCall.redisService.del(u.getLoginName());
                        return "";
                    })
                    .orElseThrow(() -> new ServiceException(zh_CN.DelNo));
            return ResultUtil.success(ResultEnum.SUCCESS);
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
    }

}
